Opik supports multimodal traces allowing you to track not just the text input
and output of your LLM, but also images, videos and audio and any other media.

<Frame>
  <img src="/img/tracing/attachments.png" />
</Frame>

## Logging Attachments

In the Python SDK, you can use the `Attachment` type to add files to your traces.
Attachements can be images, videos, audio files or any other file that you might
want to log to Opik.

Each attachment is made up of the following fields:

- `data`: The path to the file or the base64 encoded string of the file
- `content_type`: The content type of the file formatted as a MIME type

These attachements can then be logged to your traces and spans using The
`opik_context.update_current_span` and `opik_context.update_current_trace`
methods:

```python wordWrap
from opik import opik_context, track, Attachment

@track
def my_llm_agent(input):
    # LLM chain code
    # ...

    # Update the trace
    opik_context.update_current_trace(
        attachments=[
            Attachment(
                data="<path to the image>",
                content_type="image/png",
            )
        ]
    )

    return "World!"

print(my_llm_agent("Hello!"))
```

The attachements will be uploaded to the Opik platform and can be both previewed
and dowloaded from the UI.

<Frame>
  <img src="/img/tracing/attachments.png" />
</Frame>

<Note>
In order to preview the attachements in the UI, you will need to supply a
supported content type for the attachment. We support the following content types:

- Image: `image/jpeg`, `image/png`, `image/gif` and `image/svg+xml`
- Video: `video/mp4` and `video/webm`
- Audio: `audio/wav`, `audio/vorbis` and `audio/x-wav`
- Text: `text/plain` and `text/markdown`
- PDF: `application/pdf`
- Other: `application/json` and `application/octet-stream`

</Note>

## Managing Attachments Programmatically

You can also manage attachments programmatically using the [`AttachmentClient`](https://www.comet.com/docs/opik/python-sdk-reference/Objects/AttachmentClient.html):

```python wordWrap
import opik

opik_client = opik.Opik()
attachment_client = opik_client.get_attachment_client()

# Get list of attachments
attachments_details = attachment_client.get_attachment_list(
    project_name="my-project",
    entity_id="some-trace-uuid-7",
    entity_type="trace"
)

# Download an attachment
attachment_data = attachment_client.download_attachment(
    project_name="my-project",
    entity_type="trace",
    entity_id="some-trace-uuid-7",
    file_name="report.pdf",
    mime_type="application/pdf"
)

# Upload a new attachment
attachment_client.upload_attachment(
    project_name="my-project",
    entity_type="trace", 
    entity_id="some-trace-uuid-7",
    file_path="/path/to/document.pdf"
)
```

## Previewing base64 encoded images and image URLs

Opik automatically detects base64 encoded images and URLs logged to the platform,
once an image is detected we will hide the string to make the content more readable
and display the image in the UI. This is supported in the tracing view, datasets
view and experiment view.

For example if you are using the OpenAI SDK, if you pass an image to the model
as a URL, Opik will automatically detect it and display
the image in the UI:

```python wordWrap
from opik.integrations.openai import track_openai
from openai import OpenAI

# Make sure to wrap the OpenAI client to enable Opik tracing
client = track_openai(OpenAI())

response = client.chat.completions.create(
  model="gpt-4o-mini",
  messages=[
    {
      "role": "user",
      "content": [
        {"type": "text", "text": "What's in this image?"},
        {
          "type": "image_url",
          "image_url": {
            "url": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg",
          },
        },
      ],
    }
  ],
  max_tokens=300,
)

print(response.choices[0])
```

<Frame>
  <img src="/img/tracing/image_trace.png" />
</Frame>

## Embedded Attachments

When you embed base64-encoded media directly in your trace/span `input`, `output`, or `metadata` fields, Opik automatically optimizes storage and retrieval for performance.

### How It Works

For base64-encoded content larger than 250KB, Opik automatically extracts and stores it separately. This happens transparently - you don't need to change your code.

When you retrieve your traces or spans later, the attachments are automatically included by default. For faster queries when you don't need the attachment data, use the `strip_attachments=true` parameter.

### Size Limits

Opik Cloud supports embedded attachments up to **100MB per field**. This limit applies to individual string values in your `input`, `output`, or `metadata` fields.

<Note>
Base64 encoding increases file size by about 33%. For example, a 75MB video becomes ~100MB when base64-encoded.
</Note>

If you need to work with larger files:

1. **Use the Attachment API** - Upload files separately using `AttachmentClient` (recommended for files >50MB). See [Managing Attachments Programmatically](#managing-attachments-programmatically)

2. **Contact us** - [Get in touch](https://www.comet.com/site/about-us/contact-us/) if you need higher limits

3. **Self-host Opik** - Configure your own limits. See the [Self-hosting Guide](/self-host/overview)

### Best Practices

- Embed smaller files directly - Opik handles them efficiently
- For files >50MB, use the Attachment API for better performance  
- Use `strip_attachments=true` when querying if you don't need the attachment data

## Downloading attachments

You can download attachments in two ways:

1. **From the UI**: Hover over the attachments and click on the download icon
2. **Programmatically**: Use the `AttachmentClient` as shown in the examples above

<Tip>
  Let's us know on [Github](https://github.com/comet-ml/opik/issues/new/choose) if you would like to us to support
  additional image formats.
</Tip>
